package com.eternal.control;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import androidx.lifecycle.Observer;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.Spannable;
import android.text.SpannableString;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.alibaba.android.arouter.facade.annotation.Route;
import com.eternal.base.IConnectAction;
import com.eternal.base.data.RepositoryInjection;
import com.eternal.base.global.ActivityEvent;
import com.eternal.base.global.BluetoothKey;
import com.eternal.base.global.ProgressEvent;
import com.eternal.base.protocol.ProtocolTransformer;
import com.eternal.base.router.RouterFragmentPath;
import com.eternal.base.utils.GuQiangUtil;
import com.eternal.control.databinding.FragmentControlBinding;
import com.eternal.control.view.GuQiangCycleDialView;
import com.eternal.control.view.UpSpan;
import com.eternal.framework.bus.RxBus;
import com.eternal.framework.component.BaseFragment;
import com.eternal.framework.utils.Utils;
import com.eternal.widget.guqiang.DoubleCloseAddLayout;
import com.eternal.widget.guqiang.FanProgressBar;
import com.eternal.widget.guqiang.IEffectBar;
import com.eternal.widget.guqiang.SingleCloseAddProgressBar;
import com.google.common.primitives.UnsignedBytes;
import com.jakewharton.rxbinding2.view.RxView;

import java.util.Calendar;
import java.util.concurrent.TimeUnit;

import io.reactivex.functions.Consumer;

/**
 * Created by Administrator
 * On 2020/5/3
 * Description:
 *
 * @author Administrator
 */
@Route(path = RouterFragmentPath.Control.PAGE_CONTROL)
public class ControlFragment extends BaseFragment<FragmentControlBinding, ControlModel> implements IConnectAction {
    private UpSpan span = new UpSpan(8.5f);
    private IEffectBar.Factory schedFactory;
    private View now;
    private byte type;
    private boolean isFirstControl = false;

    @Override
    public int initContentView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return R.layout.fragment_control;
    }

    @Override
    public int initVariableId() {
        return BR.model;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initListener();
        bindingEvent();
        Intent intent=getActivity().getIntent();
        String mac = intent.getStringExtra(ActivityEvent.DEVICE_MAC);
        type=intent.getByteExtra(ActivityEvent.DEVICE_TYPE, (byte)1);
        byte port = intent.getByteExtra(ActivityEvent.DEVICE_PORT, (byte)0x0);
        viewModel.init(RepositoryInjection.providerDeviceRepository(), mac,port);
        initView();
        viewModel.register();
    }

    @Override
    public void connected() {
        viewModel.start();
    }

    @Override
    public void disconnected() {
        viewModel.stop();
    }

    @Override
    public void onDestroyView() {
        viewModel.save();
        super.onDestroyView();
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        if(hidden){
            viewModel.onPause();
        }else {
            viewModel.onResume();
        }
    }

    private void initView() {
        schedFactory = new IEffectBar.Factory() {
            @Override
            public String getText(int value) {
                return GuQiangUtil.stringForTimeByAmPm(value);
            }
        };
        SingleCloseAddProgressBar.Factory factory = new SingleCloseAddProgressBar.Factory() {
            @Override
            public String getText(int value) {
                if (viewModel.info != null && viewModel.info.isDegree) {
                    return Utils.getString(R.string.tip_degree_num, value);
                } else {
                    return Utils.getString(R.string.tip_fah_num, value);
                }
            }
        };
        binding.sbHighTmp.setFactory(factory);
        binding.sbLowTmp.setFactory(factory);
        factory = new SingleCloseAddProgressBar.Factory() {
            @Override
            public String getText(int value) {
                return Utils.getString(R.string.tip_percent_num, value);
            }
        };
        binding.sbHighHum.setFactory(factory);
        binding.sbLowHum.setFactory(factory);
        factory = new IEffectBar.Factory() {
            @Override
            public String getText(int value) {
                return GuQiangUtil.stringForTimeNoZero(value);
            }
        };
        binding.sbTime.setFactory(factory);
        binding.sbCycleOff.setFactory(factory);
        binding.sbCycleOn.setFactory(factory);
        int showFan = type == BluetoothKey.DEVICE_TYPE_A ? 1 : type==BluetoothKey.DEVICE_TYPE_E ? 2 : 0;
        binding.gqDial.showFan(showFan);
        binding.gqDial.showOffOrOn(type ==BluetoothKey.DEVICE_TYPE_B);
    }

    private void initListener() {
        initFanListener();
        initTimeListener();
        initTmpListener();
        initHumListener();
        initCycleListener();
        initSchedListener();
        initDialListener();
        initShowListener();
    }

    private void initFanListener() {
        binding.fpb.setStyle("", "0", "10", 0, 10);
        binding.fpb.setListener(new FanProgressBar.Listener() {
            @Override
            public void onDown(boolean isProgress) {
                viewModel.cancelUpdate();
                if (isProgress) {
                    binding.gqDial.setStartCanDraging(true);
                }else{
                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
//                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.INIT, 50));
                }
            }

            @Override
            public void onChange(int now) {
                if (viewModel.cycleModel.getValue() == BluetoothKey.MODE_OFF) {
                    viewModel.info.typeOff = (byte) now;
                } else {
                    viewModel.info.typeOn = (byte) now;
                }
                binding.gqDial.initStartOrEndAngle(now, now, 300, 0);
            }

            @Override
            public void onUp(boolean isProgress, int now) {
                viewModel.sendData();
                if (isProgress) {
                    binding.gqDial.setStartCanDraging(false);
                    binding.gqDial.invalidate();
                }
            }
        });
    }

    private void initTimeListener() {
        binding.sbTime.setListener(new IEffectBar.Listener() {
            @Override
            public void onDown(boolean isProgress) {
                viewModel.cancelUpdate();
                if (isProgress) {
                    binding.gqDial.setStartCanDraging(true);
                }else{
                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
//                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.INIT, 50));
                }
            }

            @Override
            public void onChange(int now) {
                if (viewModel.cycleModel.getValue() == BluetoothKey.MODE_TIME_ON) {
                    viewModel.info.timeOn = (char) now;
                } else {
                    viewModel.info.timeOff = (char) now;
                }
                binding.gqDial.initStartOrEndAngle(now, now, 300, 0);
            }

            @Override
            public void onUp(boolean isProgress, int now) {
                if (viewModel.cycleModel.getValue() == BluetoothKey.MODE_TIME_ON) {
                    viewModel.info.timeOn = (char) now;
                } else {
                    viewModel.info.timeOff = (char) now;
                }
                viewModel.sendData();
                if (isProgress) {
                    binding.gqDial.setStartCanDraging(false);
                    binding.gqDial.invalidate();
                }
            }

            @Override
            public void onChecked(boolean b) {
            }
        });
    }

    private void initTmpListener() {
        binding.layoutTmp.setListener(new DoubleListenerAdapter() {
            @Override
            public void onFirst(int value) {
                viewModel.info.autoHighTmp = UnsignedBytes.checkedCast(value);
                if (!viewModel.info.isControlTypeByHum) {
                    int l = UnsignedBytes.toInt(viewModel.info.autoLowTmp);
                    if (!viewModel.info.isDegree) {
                        value -= 32;
                        l -= 32;
                    }
                    binding.gqDial.initStartOrEndAngle(l, l, value, value);
                }
            }

            @Override
            public void onLast(int value) {
                viewModel.info.autoLowTmp = UnsignedBytes.checkedCast(value);
                if (!viewModel.info.isControlTypeByHum) {
                    int h = UnsignedBytes.toInt(viewModel.info.autoHighTmp);
                    if (!viewModel.info.isDegree) {
                        value -= 32;
                        h -= 32;
                    }
                    binding.gqDial.initStartOrEndAngle(value, value, h, h);
                }
            }

            @Override
            public void onEndFirst(boolean isProgress, int value) {
                viewModel.info.autoHighTmp = UnsignedBytes.checkedCast(value);
                super.onEndFirst(isProgress, value);
                if (viewModel.isRefreshComplete && viewModel.info.isControlTypeByHum) {
                    viewModel.controlTypeByHumModel.setValue(!viewModel.controlTypeByHumModel.getValue());
                }
            }

            @Override
            public void onEndLast(boolean isProgress, int value) {
                viewModel.info.autoLowTmp = UnsignedBytes.checkedCast(value);
                super.onEndLast(isProgress, value);
                if (viewModel.isRefreshComplete && viewModel.info.isControlTypeByHum) {
                    viewModel.controlTypeByHumModel.setValue(!viewModel.controlTypeByHumModel.getValue());
                }
            }

            @Override
            public void onFirstChecked(boolean b) {
                viewModel.info.autoHighTmpSwitch = b;
                if(!viewModel.info.isControlTypeByHum){
                    if(binding.gqDial.getEnd()!=b){
                        binding.gqDial.setEnd(b);
                    }
                }else if (viewModel.isRefreshComplete){
                    viewModel.controlTypeByHumModel.setValue(!viewModel.controlTypeByHumModel.getValue());
                }
                super.onFirstChecked(b);
            }

            @Override
            public void onLastChecked(boolean b) {
                viewModel.info.autoLowTmpSwitch = b;
                if(!viewModel.info.isControlTypeByHum){
                    if(binding.gqDial.getStart()!=b){
                        binding.gqDial.setStart(b);
                    }
                } else if (viewModel.isRefreshComplete){
                    viewModel.controlTypeByHumModel.setValue(!viewModel.controlTypeByHumModel.getValue());
                }
                super.onLastChecked(b);
            }
        });
    }

    private void initHumListener() {
        binding.layoutHum.setListener(new DoubleListenerAdapter() {
            @Override
            public void onFirst(int value) {
                viewModel.info.autoHighHum = UnsignedBytes.checkedCast(value);
                if (viewModel.info.isControlTypeByHum) {
                    int h = viewModel.info.autoHighHum;
                    int l = viewModel.info.autoLowHum;
                    binding.gqDial.initStartOrEndAngle(l, l, h, h);
                }
            }

            @Override
            public void onLast(int value) {
                viewModel.info.autoLowHum = UnsignedBytes.checkedCast(value);
                if (viewModel.info.isControlTypeByHum) {
                    int h = viewModel.info.autoHighHum;
                    int l = viewModel.info.autoLowHum;
                    binding.gqDial.initStartOrEndAngle(l, l, h, h);
                }
            }

            @Override
            public void onEndFirst(boolean isProgress, int value) {
                viewModel.info.autoHighHum = UnsignedBytes.checkedCast(value);
                super.onEndFirst(isProgress, value);
                if (viewModel.isRefreshComplete && !viewModel.info.isControlTypeByHum) {
                    viewModel.controlTypeByHumModel.setValue(!viewModel.controlTypeByHumModel.getValue());
                }
            }

            @Override
            public void onEndLast(boolean isProgress, int value) {
                viewModel.info.autoLowHum = UnsignedBytes.checkedCast(value);
                super.onEndLast(isProgress, value);
                if (viewModel.isRefreshComplete && !viewModel.info.isControlTypeByHum) {
                    viewModel.controlTypeByHumModel.setValue(!viewModel.controlTypeByHumModel.getValue());
                }
            }

            @Override
            public void onFirstChecked(boolean b) {
                viewModel.info.autoHighHumSwitch = b;
                if(viewModel.info.isControlTypeByHum){
                    if(binding.gqDial.getEnd()!=b){
                        binding.gqDial.setEnd(b);
                    }
                }else if (viewModel.isRefreshComplete){
                    viewModel.controlTypeByHumModel.setValue(!viewModel.controlTypeByHumModel.getValue());
                }
                super.onFirstChecked(b);
            }

            @Override
            public void onLastChecked(boolean b) {
                viewModel.info.autoLowHumSwitch = b;
                if(viewModel.info.isControlTypeByHum){
                    if(binding.gqDial.getStart()!=b){
                        binding.gqDial.setStart(b);
                    }
                }else if (viewModel.isRefreshComplete){
                    viewModel.controlTypeByHumModel.setValue(!viewModel.controlTypeByHumModel.getValue());
                }
                super.onLastChecked(b);
            }
        });
    }

    @SuppressLint("CheckResult")
    private void initShowListener() {
        RxView.clicks(binding.txtShow)
                .throttleFirst(1, TimeUnit.SECONDS)
                .subscribe(new Consumer<Object>() {
                    @Override
                    public void accept(Object o) {
                        viewModel.controlTypeByHumModel.setValue(!viewModel.controlTypeByHumModel.getValue());
                    }
                });
    }

    private void switchControlType(boolean isControlTypeByHum, final boolean isShowAnimate) {
        viewModel.info.isControlTypeByHum = isControlTypeByHum;
        viewModel.setControlTypeByHum(isControlTypeByHum);
        //湿度圆环上移到温度圆环360
        binding.txtShow.animate().setDuration(isShowAnimate ? 1000 : 1).rotationBy(360).setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                binding.txtShow.setRotation(0);
                if (viewModel.info.isControlTypeByHum) {
                    if (viewModel.info.isDegree) {
                        viewModel.show.setValue(Utils.getString(R.string.tip_degree_num,
                                ProtocolTransformer.getString4Degree(viewModel.info.tmp, true)));
                    } else {
                        viewModel.show.setValue(Utils.getString(R.string.tip_fah_num,
                                ProtocolTransformer.getString4Degree(viewModel.info.tmp, false)));
                    }
                } else {
                    viewModel.show.setValue(Utils.getString(R.string.tip_percent_num,
                            ProtocolTransformer.getPer(viewModel.info.hum)));
                }
            }
        }).start();
        binding.gqDial.animate().setDuration(isShowAnimate ? 1000 : 1).rotationBy(360).setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                binding.gqDial.setRotation(0);
                String unit, value;
                if (viewModel.info.isControlTypeByHum) {
                    value = ProtocolTransformer.getPer(viewModel.info.hum);
                    unit = "%";
                } else {
                    if (viewModel.info.isDegree) {
                        unit = "℃";
                        value = ProtocolTransformer.getString4Degree(viewModel.info.tmp, true);
                    } else {
                        unit = "℉";
                        value = ProtocolTransformer.getString4Degree(viewModel.info.tmp, false);
                    }
                }
                binding.gqDial.setTmp(value, unit);
                if (viewModel.cycleModel.getValue() == BluetoothKey.MODE_AUTO) {
                    int h, l;
                    if (viewModel.info.isControlTypeByHum) {
                        binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_AUTO_HUM);
                        h = viewModel.info.autoLowHum;
                        l = viewModel.info.autoHighHum;
                        binding.gqDial.initStartOrEndAngle(h, h, l, l);
                        l = 0;
                        if (viewModel.info.hum != BluetoothKey.EMPTY) {
                            l = Math.round(viewModel.info.hum / 100f);
                        }
                    } else {
                        if (viewModel.info.isDegree) {
                            binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_AUTO_TMP_C);
                            h = viewModel.info.autoHighTmp;
                            l = viewModel.info.autoLowTmp;
                        } else {
                            binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_AUTO_TMP_F);
                            h = UnsignedBytes.toInt(viewModel.info.autoHighTmp) - 32;
                            l = UnsignedBytes.toInt(viewModel.info.autoLowTmp) - 32;
                        }
                        binding.gqDial.initStartOrEndAngle(l, l, h, h);
                        l = ProtocolTransformer.getTmp(viewModel.info.tmp, viewModel.info.isDegree);
                    }
                    binding.gqDial.setStatusLineAndCenterText(String.valueOf(l), "");
                }
                if (isShowAnimate) {
                    binding.gqDial.startAnimation();
                }
            }

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
            }
        }).start();
        if (isShowAnimate) {
            binding.gqDial.startAnimation();
        }
        // 如果是Auto模式，参数设置区自动滚动到相应位置
        if (viewModel.info.workType == BluetoothKey.MODE_AUTO) {
            binding.scContent.post(new Runnable() {
                @Override
                public void run() {
                    if (viewModel.info.isControlTypeByHum) {
                        if (isShowAnimate) {
                            binding.scContent.smoothScrollTo(0,binding.layoutHum.getTop());
                        } else {
                            binding.scContent.scrollTo(0,binding.layoutHum.getTop());
                        }
                    } else {
                        if (isShowAnimate) {
                            binding.scContent.smoothScrollTo(0,binding.layoutTmp.getTop());
                        } else {
                            binding.scContent.scrollTo(0,binding.layoutTmp.getTop());
                        }
                    }
                }
            });
        }
    }

    private void initSchedListener() {
        binding.layoutCs.setListener(new DoubleListenerAdapter() {
            @Override
            public void onFirstDown(boolean isProgress) {
                viewModel.cancelUpdate();
                if (isProgress) {
                    binding.gqDial.setStartCanDraging(true);
                }else{
                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
//                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.INIT, 50));
                }
            }

            @Override
            public void onLastDown(boolean isProgress) {
                viewModel.cancelUpdate();
                if (isProgress) {
                    binding.gqDial.setEndCanDraging(true);
                }else{
                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
//                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.INIT, 50));
                }
            }

            @Override
            public void onFirst(int value) {
                viewModel.info.schedOn = (char) (value);
                binding.gqDial.initStartOrEndAngle(value, value, viewModel.info.schedOff, viewModel.info.schedOff);
            }

            @Override
            public void onLast(int value) {
                viewModel.info.schedOff = (char) value;
                binding.gqDial.initStartOrEndAngle(viewModel.info.schedOn, viewModel.info.schedOn, value, value);
            }

            @Override
            public void onEndFirst(boolean isProgress, int value) {
                viewModel.info.schedOn = (char) value;

                viewModel.sendData();
                if (isProgress) {
                    binding.gqDial.setStartCanDraging(false);
                    binding.gqDial.invalidate();
                }
            }

            @Override
            public void onEndLast(boolean isProgress, int value) {
                viewModel.info.schedOff = (char) value;
                viewModel.sendData();
                if (isProgress) {
                    binding.gqDial.setEndCanDraging(false);
                    binding.gqDial.invalidate();
                }
            }

            @Override
            public void onFirstChecked(boolean b) {
            }

            @Override
            public void onLastChecked(boolean b) {
            }
        });
    }

    private void initCycleListener() {
        binding.sbCycleOn.setListener(new IEffectBar.Listener() {
            @Override
            public void onDown(boolean isProgress) {
                viewModel.cancelUpdate();
                if (isProgress) {
                    binding.gqDial.setStartCanDraging(true);
                }else{
                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
//                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.INIT, 50));
                }
            }

            @Override
            public void onChange(int now) {
                viewModel.info.cycleOn = (char) now;
                binding.gqDial.initStartOrEndAngle(now, now, viewModel.info.cycleOff, viewModel.info.cycleOff);
            }

            @Override
            public void onUp(boolean isProgress, int now) {
                viewModel.info.cycleOn = (char) now;
                viewModel.sendData();
                if (isProgress) {
                    binding.gqDial.setStartCanDraging(false);
                    binding.gqDial.invalidate();
                }
            }

            @Override
            public void onChecked(boolean b) {
            }
        });
        binding.sbCycleOff.setListener(new IEffectBar.Listener() {
            @Override
            public void onDown(boolean isProgress) {
                viewModel.cancelUpdate();
                if (isProgress) {
                    binding.gqDial.setEndCanDraging(true);
                }else{
                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
//                    RxBus.getDefault().post(new ProgressEvent(ProgressEvent.INIT, 50));
                }
            }

            @Override
            public void onChange(int now) {
                viewModel.info.cycleOff = (char) now;
                binding.gqDial.initStartOrEndAngle(viewModel.info.cycleOn, viewModel.info.cycleOn, now, now);
            }

            @Override
            public void onUp(boolean isProgress, int now) {
                viewModel.info.cycleOff = (char) now;
                viewModel.sendData();
                if (isProgress) {
                    binding.gqDial.setEndCanDraging(false);
                    binding.gqDial.invalidate();
                }
            }

            @Override
            public void onChecked(boolean b) {
            }
        });
    }

    private void initDialListener() {
        binding.gqDial.setOnChangeListeners(new GuQiangCycleDialView.OnChangeListeners() {
            @Override
            public void onChangeTouchStart(boolean isStart) {
                viewModel.cancelUpdate();
                if (BluetoothKey.MODE_AUTO == viewModel.cycleModel.getValue()) {
                    if (viewModel.info.isControlTypeByHum) {
                        if (isStart) {
                            if (!binding.sbLowHum.isChecked()) {
                                binding.gqDial.setStart(true);
                                binding.sbLowHum.setChecked(true);
                            }
                        } else {
                            if (!binding.sbHighHum.isChecked()) {
                                binding.gqDial.setEnd(true);
                                binding.sbHighHum.setChecked(true);
                            }
                        }
                    } else {
                        if (isStart) {
                            if (!binding.sbLowTmp.isChecked()) {
                                binding.gqDial.setStart(true);
                                binding.sbLowTmp.setChecked(true);
                            }
                        } else {
                            if (!binding.sbHighTmp.isChecked()) {
                                binding.gqDial.setEnd(true);
                                binding.sbHighTmp.setChecked(true);
                            }
                        }
                    }
                }
            }

            @Override
            public void onChangeStartAndEnd(int start, int end) {
                switch (viewModel.cycleModel.getValue()) {
                    case BluetoothKey.MODE_OFF:
                    case BluetoothKey.MODE_ON:
                        binding.fpb.setProgress(start);
                        break;
                    case BluetoothKey.MODE_TIME_OFF:
                    case BluetoothKey.MODE_TIME_ON:
                        binding.sbTime.setProgress(start);
                        break;
                    case BluetoothKey.MODE_CYCLE:
                        binding.sbCycleOn.setProgress(start);
                        binding.sbCycleOff.setProgress(end);
                        break;
                    case BluetoothKey.MODE_SCHED:
                        binding.sbFirst.setProgress(start);
                        binding.sbLast.setProgress(end);
                        break;
                    default:
                        if (viewModel.info.isControlTypeByHum) {
                            binding.sbLowHum.setProgress(start);
                            binding.sbHighHum.setProgress(end);
                        } else {
                            if (viewModel.info.isDegree) {
                                binding.sbLowTmp.setProgress(start);
                                binding.sbHighTmp.setProgress(end);
                            } else {
                                binding.sbLowTmp.setProgress(start + 32);
                                binding.sbHighTmp.setProgress(end + 32);
                            }
                        }
                }
            }

            @Override
            public void onChangeAndEndByTouchEnd(int start, int end) {
                viewModel.sendData();
            }
        });
    }

    private void bindingEvent() {
        viewModel.show.observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable String s) {
                SpannableString spannable = new SpannableString(s);
                spannable.setSpan(span, spannable.length() - 1, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                binding.txtShow.setText(spannable);
            }
        });

        viewModel.controlTypeByHumModel.observe(this, new Observer<Boolean>() {
            @Override
            public void onChanged(@Nullable Boolean result) {
                switchControlType(result,viewModel.isRefreshComplete && isFirstControl);
                if (!isFirstControl) {
                    isFirstControl = true;
                }
            }
        });

        viewModel.expand.observe(this, new Observer<Boolean>() {
            @Override
            public void onChanged(@Nullable Boolean result) {
                if (result) {
                    binding.elModeType.expand();
                } else {
                    binding.elModeType.collapse();
                }
            }
        });

        viewModel.cycleModel.observe(this, new Observer<Byte>() {
            @Override
            public void onChanged(@Nullable Byte model) {
                switch (model) {
                    case 0x1:
                        viewModel.model.setValue(Utils.getString(R.string.tip_control_off));
                        binding.txtMode.setTextSize(12);
                        binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_OFF);
                        initOff();
                        break;
                    case 0x2:
                        viewModel.model.setValue(Utils.getString(R.string.tip_control_on));
                        binding.txtMode.setTextSize(12);
                        binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_ON);
                        initOn();
                        break;
                    case 0x3:
                        viewModel.model.setValue(Utils.getString(R.string.tip_control_auto));
                        binding.txtMode.setTextSize(12);
                        if (viewModel.info.isControlTypeByHum) {
                            binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_AUTO_HUM);
                        } else if (viewModel.info.isDegree) {
                            binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_AUTO_TMP_C);
                        } else {
                            binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_AUTO_TMP_F);
                        }
                        initAuto();
                        break;
                    case 0x4:
                        viewModel.model.setValue(Utils.getString(R.string.tip_control_time_to_on));
                        binding.txtMode.setTextSize(10);
                        binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_TIME_TO_ON);
                        initTimeOn();
                        break;
                    case 0x5:
                        viewModel.model.setValue(Utils.getString(R.string.tip_control_time_to_off));
                        binding.txtMode.setTextSize(10);
                        binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_TIME_TO_OFF);
                        initTimeOff();
                        break;
                    case 0x6:
                        viewModel.model.setValue(Utils.getString(R.string.tip_control_cycle));
                        binding.txtMode.setTextSize(12);
                        binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_CYCLE);
                        initCycle();
                        break;
                    default:
                        viewModel.model.setValue(Utils.getString(R.string.tip_control_sched));
                        binding.txtMode.setTextSize(12);
                        binding.gqDial.setModeType(GuQiangCycleDialView.MODE_TYPE_SCHEDULE);
                        initSched();
                }
            }
        });
    }

    private void initAuto() {
        if (now != binding.layoutTh) {
            if (now != null) {
                now.setVisibility(View.GONE);
            }
            binding.layoutTh.setVisibility(View.VISIBLE);
        }
        now = binding.layoutTh;
        if (viewModel.info.isDegree) {
            String min = Utils.getString(R.string.tip_min_degree_tmp), max = Utils.getString(R.string.tip_max_degree_tmp);
            binding.sbHighTmp.setValue(min, max, 0, 90);
            binding.sbLowTmp.setValue(min, max, 0, 90);
        } else {
            String min = Utils.getString(R.string.tip_min_fah_tmp), max = Utils.getString(R.string.tip_max_fah_tmp);
            binding.sbHighTmp.setValue(min, max, 32, 162);
            binding.sbLowTmp.setValue(min, max, 32, 162);
        }
        if (viewModel.isRefreshComplete && viewModel.lastInfo != null) {
            if (viewModel.lastInfo.autoHighTmp != viewModel.info.autoHighTmp
                    || viewModel.lastInfo.autoLowTmp != viewModel.info.autoLowTmp
                    || viewModel.lastInfo.autoHighTmpSwitch!= viewModel.info.autoHighTmpSwitch
                    || viewModel.lastInfo.autoLowTmpSwitch != viewModel.info.autoLowTmpSwitch) {
                if (viewModel.controlTypeByHumModel.getValue() != null && viewModel.controlTypeByHumModel.getValue() && viewModel.lastInfo.isDegree == viewModel.info.isDegree) {
                    viewModel.controlTypeByHumModel.setValue(false);
                }
            } else if (viewModel.lastInfo.autoHighHum != viewModel.info.autoHighHum
                    || viewModel.lastInfo.autoLowHum != viewModel.info.autoLowHum
                    || viewModel.lastInfo.autoHighHumSwitch != viewModel.info.autoHighHumSwitch
                    || viewModel.lastInfo.autoLowHumSwitch != viewModel.info.autoLowHumSwitch) {
                if (viewModel.controlTypeByHumModel.getValue() == null || !viewModel.controlTypeByHumModel.getValue()) {
                    viewModel.controlTypeByHumModel.setValue(true);
                }
            }
        }

        binding.sbHighTmp.setProgress(UnsignedBytes.toInt(viewModel.info.autoHighTmp));
        binding.sbLowTmp.setProgress(UnsignedBytes.toInt(viewModel.info.autoLowTmp));
        binding.sbHighHum.setProgress(viewModel.info.autoHighHum);
        binding.sbLowHum.setProgress(viewModel.info.autoLowHum);
        binding.sbHighTmp.setChecked(viewModel.info.autoHighTmpSwitch);
        binding.sbLowTmp.setChecked(viewModel.info.autoLowTmpSwitch);
        binding.sbHighHum.setChecked(viewModel.info.autoHighHumSwitch);
        binding.sbLowHum.setChecked(viewModel.info.autoLowHumSwitch);
        int h, l;
        if (viewModel.info.isControlTypeByHum) {
            initDial(ProtocolTransformer.getTimeWithAMPM(System.currentTimeMillis()),
                    viewModel.info.humState);
            h = viewModel.info.autoHighHum;
            l = viewModel.info.autoLowHum;
            binding.gqDial.initStartOrEndAngle(l, l, h, h);
            l = 0;
            if (viewModel.info.hum != BluetoothKey.EMPTY) {
                l = Math.round(viewModel.info.hum / 100f);
            }
            binding.gqDial.setStart(viewModel.info.autoLowHumSwitch);
            binding.gqDial.setEnd(viewModel.info.autoHighHumSwitch);
            binding.gqDial.setStatusLineAndCenterText(String.valueOf(l), "");
        } else {
            initDial(ProtocolTransformer.getTimeWithAMPM(System.currentTimeMillis()),
                    viewModel.info.tmpState);
            h = UnsignedBytes.toInt(viewModel.info.autoHighTmp);
            l = UnsignedBytes.toInt(viewModel.info.autoLowTmp);

            if (!viewModel.info.isDegree) {
                h -= 32;
                l -= 32;
                if (h < 0) {
                    h = 0;
                }
                if (l < 0) {
                    l = 0;
                }
            }
            binding.gqDial.setStart(viewModel.info.autoLowTmpSwitch);
            binding.gqDial.setEnd(viewModel.info.autoHighTmpSwitch);
            binding.gqDial.initStartOrEndAngle(l, l, h, h);
            l = ProtocolTransformer.getTmp(viewModel.info.tmp, viewModel.info.isDegree);
            binding.gqDial.setStatusLineAndCenterText(String.valueOf(l), "");
        }
    }

    private void initOff() {
        if (now != binding.llFan) {
            if (now != null) {
                now.setVisibility(View.GONE);
            }
            if(type==BluetoothKey.DEVICE_TYPE_A || type==BluetoothKey.DEVICE_TYPE_E){
                binding.llFan.setVisibility(View.VISIBLE);
            }
        }
        now = binding.llFan;
        binding.fpb.setTitle(Utils.getString(R.string.title_control_min_fan));
        int value = viewModel.info.typeOff;
        binding.fpb.setProgress(value);
        binding.gqDial.initStartOrEndAngle(value, value, 300, 0);
        initDial(ProtocolTransformer.getTimeWithAMPM(System.currentTimeMillis()),
                viewModel.info.fanState);
    }

    private void initDial(String time, byte status) {
        String value, unit;
        if (viewModel.info.isControlTypeByHum) {
            unit = "%";
            value = ProtocolTransformer.getPer(viewModel.info.hum);
            if (viewModel.info.isDegree) {
                viewModel.show.setValue(Utils.getString(R.string.tip_degree_num,
                        ProtocolTransformer.getString4Degree(viewModel.info.tmp, true)));
            } else {
                viewModel.show.setValue(Utils.getString(R.string.tip_fah_num,
                        ProtocolTransformer.getString4Degree(viewModel.info.tmp, false)));
            }
        } else {
            if (viewModel.info.isDegree) {
                unit = "℃";
            } else {
                unit = "℉";
            }
            value = ProtocolTransformer.getString4Degree(viewModel.info.tmp, viewModel.info.isDegree);
            viewModel.show.setValue(Utils.getString(R.string.tip_percent_num,
                    ProtocolTransformer.getPer(viewModel.info.hum)));
        }
        binding.gqDial.setInnerCircleText(value, unit,
                time, String.valueOf(viewModel.info.fan), status);
    }

    private void initOn() {
        if (now != binding.llFan) {
            if (now != null) {
                now.setVisibility(View.GONE);
            }
            if(type==BluetoothKey.DEVICE_TYPE_A || type==BluetoothKey.DEVICE_TYPE_E){
                binding.llFan.setVisibility(View.VISIBLE);
            }
        }
        now = binding.llFan;
        binding.fpb.setTitle(Utils.getString(R.string.title_control_fan));
        int value = viewModel.info.typeOn;
        binding.fpb.setProgress(value);
        binding.gqDial.initStartOrEndAngle(value, value, 300, 0);
        initDial(ProtocolTransformer.getTimeWithAMPM(System.currentTimeMillis()),
                viewModel.info.fanState);
    }

    private void initCycle() {
        if (now != binding.layoutCycle) {
            if (now != null) {
                now.setVisibility(View.GONE);
            }
            binding.layoutCycle.setVisibility(View.VISIBLE);
        }
        now = binding.layoutCycle;
        int start = viewModel.info.cycleOn;
        int end = viewModel.info.cycleOff;
        binding.sbCycleOn.setProgress(start);
        binding.sbCycleOff.setProgress(end);
        binding.gqDial.initStartOrEndAngle(start, start, end, end);
        initDial(ProtocolTransformer.getTimeWithAMPM(System.currentTimeMillis()), (byte) 0);
        start = viewModel.info.currentTypeResidueTime;
        binding.gqDial.setStatusLineAndCenterText(String.valueOf(start),
                viewModel.info.currentTypeResidueOn ? "1" : "0");
    }

    private void initSched() {
        if (now != binding.layoutCs) {
            if (now != null) {
                now.setVisibility(View.GONE);
            }
            binding.layoutCs.setVisibility(View.VISIBLE);
        }
        now = binding.layoutCs;
        binding.sbFirst.setType(Utils.getString(R.string.title_control_start_time),
                Utils.getString(R.string.tip_control_12_am), Utils.getString(R.string.tip_control_12_pm),
                0, 1440);
        binding.sbFirst.setFactory(schedFactory);
        binding.sbLast.setType(Utils.getString(R.string.title_control_end_time),
                Utils.getString(R.string.tip_control_12_am), Utils.getString(R.string.tip_control_12_pm),
                0, 1440);
        binding.sbLast.setFactory(schedFactory);
        int start = viewModel.info.schedOn;
        int end = viewModel.info.schedOff;
        binding.sbFirst.setProgress(start);
        binding.sbLast.setProgress(end);
        binding.gqDial.initStartOrEndAngle(start, start, end, end);
        //可以对每个时间域单独修改
        Calendar c = Calendar.getInstance();
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        int second = c.get(Calendar.SECOND);
        long seconds = hour * 60 * 60 + minute * 60 + second;
        String time = ((hour%12==0) ? "12" : String.valueOf(hour%12)) + ":" + (minute>9 ? minute : "0"+minute);
        initDial(time, (byte) 0);
        binding.gqDial.setStatusLineAndCenterText(String.valueOf(seconds), hour > 12 ? "PM" : "AM");
    }

    private void initTimeOff() {
        if (now != binding.layoutTime) {
            if (now != null) {
                now.setVisibility(View.GONE);
            }
            binding.layoutTime.setVisibility(View.VISIBLE);
        }
        now = binding.layoutTime;
        binding.sbTime.setType(Utils.getString(R.string.title_control_time_off),
                Utils.getString(R.string.tip_min_time), Utils.getString(R.string.tip_max_time),
                0, 1440);
        int value = viewModel.info.timeOff;
        binding.sbTime.setProgress(value);
        binding.gqDial.initStartOrEndAngle(value, value, 300, 0);
        initDial(ProtocolTransformer.getTimeWithAMPM(System.currentTimeMillis()), (byte) 0);
        value = viewModel.info.currentTypeResidueTime;
        binding.gqDial.setStatusLineAndCenterText(String.valueOf(value), "0");
    }

    private void initTimeOn() {
        if (now != binding.layoutTime) {
            if (now != null) {
                now.setVisibility(View.GONE);
            }
            binding.layoutTime.setVisibility(View.VISIBLE);
        }
        now = binding.layoutTime;
        binding.layoutTime.setVisibility(View.VISIBLE);
        binding.sbTime.setType(Utils.getString(R.string.title_control_time_on),
                Utils.getString(R.string.tip_min_time), Utils.getString(R.string.tip_max_time),
                0, 1440);
        int value = viewModel.info.timeOn;
        binding.sbTime.setProgress(value);
        binding.gqDial.initStartOrEndAngle(value, value, 300, 0);
        value = viewModel.info.currentTypeResidueTime;
        initDial(ProtocolTransformer.getTimeWithAMPM(System.currentTimeMillis()), (byte) 0);
        binding.gqDial.setStatusLineAndCenterText(String.valueOf(value), "1");
    }

    abstract class DoubleListenerAdapter implements DoubleCloseAddLayout.Listener {

        @Override
        public void onFirstDown(boolean isProgress) {
            viewModel.cancelUpdate();
            if (isProgress) {
                binding.gqDial.setEndCanDraging(true);
            }else{
                RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
//                RxBus.getDefault().post(new ProgressEvent(ProgressEvent.INIT, 50));
            }
        }

        @Override
        public void onLastDown(boolean isProgress) {
            viewModel.cancelUpdate();
            if (isProgress) {
                binding.gqDial.setStartCanDraging(true);
            }else{
                RxBus.getDefault().post(new ProgressEvent(ProgressEvent.END));
//                RxBus.getDefault().post(new ProgressEvent(ProgressEvent.INIT, 50));
            }
        }

        @Override
        public void onFirstChecked(boolean b) {
            if(!viewModel.refreshStopped){
                viewModel.cancelUpdate();
                viewModel.sendData();
            }
        }

        @Override
        public void onLastChecked(boolean b) {
            if(!viewModel.refreshStopped){
                viewModel.cancelUpdate();
                viewModel.sendData();
            }
        }

        @Override
        public void onEndFirst(boolean isProgress, int value) {
            viewModel.sendData();
            if (isProgress) {
                binding.gqDial.setEndCanDraging(false);
                binding.gqDial.invalidate();
            }
        }

        @Override
        public void onEndLast(boolean isProgress, int value) {
            viewModel.sendData();
            if (isProgress) {
                binding.gqDial.setStartCanDraging(false);
                binding.gqDial.invalidate();
            }
        }
    }
}
